import { css } from "@emotion/react"
import { LoginOtpCodeForm } from "../data"
import { useEffect, useMemo, useRef } from "react"
import { motion } from "motion/react"
import styled from "@emotion/styled"
import Svg from "@/components/base/Svg"
import { createLogger } from "@/utils/logger"
import { atom, useAtom, useAtomValue, useSetAtom } from "jotai"

const logger = createLogger("PhoneInputFormItem")

const focusedAtom = atom(false)

const Container = styled(motion.div)`
    display: flex;
    flex-direction: row;
    gap: 1rem;
    border-radius: 8rem;
`

type Props = Omit<ExtractStyledProps<typeof Container>, "children">
export default function OtpCodeInputFormItem({ ...props }: Props) {
    const {
        //
        className: _className,
        style: _style,
        css: _css,
        ...rest
    } = props
    const setFocused = useSetAtom(focusedAtom)

    const form = LoginOtpCodeForm.useFormContext()
    const inputRef = useRef<HTMLInputElement>(null)
    const code = form.watch("code")

    const disabledCodeInput = useMemo(() => {
        return code.length === 6 && form.formState.isSubmitting && !form.formState.isValid
    }, [code, form.formState.isSubmitting, form.formState.isValid])

    useEffect(() => {
        const handle = setTimeout(() => {
            const clickHandler = () => {
                if (inputRef.current) {
                    inputRef.current.focus()
                    inputRef.current.click()
                    document.removeEventListener('click', clickHandler)
                }
            }

            document.addEventListener('click', clickHandler)
            document.documentElement.click()
        }, 300)

        return () => clearTimeout(handle)
    }, [])

    return (
        <LoginOtpCodeForm.ErrorWrapper
            css={css`
                display: flex;
                flex-direction: column;
                gap: 8rem;
                align-items: stretch;
                background: transparent;
            `}
            field="code"
            render={({ error }) => {
                return (
                    <motion.caption
                        animate={{
                            opacity: error ? 1 : 0,
                        }}
                        css={css`
                            color: #cc0033;
                            align-self: flex-start;
                            display: flex;
                            flex-direction: row;
                            gap: 4rem;
                            align-items: center;
                            font-size: 12rem;
                            line-height: 16rem;
                            font-weight: 500;
                            font-family: "Gilroy", monospace;
                            height: 20rem;
                        `}
                    >
                        <Svg
                            css={css`
                                width: 16rem;
                                height: 16rem;
                            `}
                            src="login/error_head.svg"
                        />
                        {error?.message}
                    </motion.caption>
                )
            }}
        >
            <Container
                style={{
                    ..._style,
                }}
                css={css`
                    position: relative;
                    display: flex;
                    flex-direction: column;
                    justify-content: center;
                    align-items: center;
                    cursor: pointer;
                `}
                className={_className}
                onClick={(ev) => {
                    ev.stopPropagation()
                    ev.preventDefault()
                    if (inputRef.current) {
                        inputRef.current.focus()
                        inputRef.current.click()
                    }
                    setFocused(true)
                }}
            >
                <LoginOtpCodeForm.BaseItem
                    label="Code"
                    field="code"
                    options={{
                        validate: (value) => {
                            if (value.length === 0) {
                                return "Please enter the code"
                            }
                            if (value.length < 6) {
                                return "Please enter the correct code"
                            }
                            return true
                        },
                    }}
                    render={() => {
                        return (
                            <input
                                disabled={disabledCodeInput}
                                css={css`
                                    position: absolute;
                                    opacity: 0.01;
                                    top: 0;
                                    left: 0;
                                    width: 100%;
                                    height: 100%;
                                    z-index: 1;
                                `}
                                ref={inputRef}
                                type="text"
                                inputMode="numeric"
                                maxLength={6}
                                autoComplete="off"
                                autoFocus
                                value={form.watch("code")}
                                onChange={(e) => {
                                    if (e.target.value.length < form.watch("code").length) {
                                        form.setValue("code", "")
                                    } else {
                                        form.setValue("code", e.target.value)
                                    }
                                    form.trigger("code")
                                }}
                                onFocus={(ev) => {
                                    ev.preventDefault()
                                    setFocused(true)
                                    ev.currentTarget.click()
                                }}
                                onBlur={() => {
                                    setFocused(false)
                                }}
                            />
                        )
                    }}
                />
                <OtpCodeRow code={form.watch("code")} />
            </Container>
        </LoginOtpCodeForm.ErrorWrapper>
    )
}

function OtpCodeCube({ char, active }: { char: string; active: boolean }) {
    const focused = useAtomValue(focusedAtom)
    return (
        <motion.div
            css={css`
                position: relative;
                width: 48rem;
                height: 48rem;
                border-radius: 8rem;
                background-color: #f2f3f5;
                display: flex;
                justify-content: center;
                align-items: center;
                font-family: Gilroy;
                font-weight: 500;
                font-size: 32rem;
                line-height: 0rem;
                letter-spacing: 0%;
                text-align: center;
                color: #0f0f10;
                padding-top: 3rem;

                @keyframes blinking {
                    0% {
                        color: #0f0f10;
                    }
                    50% {
                        color: #0f0f1000;
                    }
                    100% {
                        color: #0f0f10;
                    }
                }
                ${active && focused ? `animation: blinking 1s infinite;` : ""}

                /* 中間有個小圓點 "*"" 閃爍 */
                &::after {
                    @keyframes cursor {
                        0% {
                            opacity: 0;
                        }
                        50% {
                            opacity: 1;
                        }
                        100% {
                            opacity: 0;
                        }
                    }
                    display: ${active && focused ? "flex" : "none"};
                    content: "*";
                    position: absolute;
                    justify-content: center;
                    align-items: center;
                    top: 0;
                    left: 0;
                    right: 0;
                    bottom: 0;
                    font-weight: 900;
                    font-size: 24rem;
                    line-height: 0rem;
                    font-family: "Roboto", sans-serif;
                    animation: cursor 1s infinite;
                    color: #1e71ff;
                    padding-top: 6rem;
                }
            `}
            animate={{
                boxShadow: active ? "0 0 1rem 1rem #1e71ff inset" : "0 0 1rem 1rem #b8bdcc inset",
                backgroundColor: active ? "#FFFFFF" : "#F2F3F5",
            }}
        >
            {char}
        </motion.div>
    )
}

function OtpCodeRow({ code }: { code: string }) {
    const activeIndex = useMemo(() => {
        return code.length
    }, [code])
    return (
        <div
            css={css`
                display: flex;
                flex-direction: row;
                gap: 8rem;
            `}
        >
            {Array(6)
                .fill(null)
                .map((_, index) => (
                    <OtpCodeCube
                        active={index === activeIndex}
                        key={index}
                        char={code[index] ?? ""}
                    />
                ))}
        </div>
    )
}
